﻿namespace Minesweeper
{
    using System;

    public class Cell
    {
        private const char block = (char)0x2588;
        public const int CellHeight = 5;
        public const int CellWidth = 3;
        private ConsoleColor[] digitsColors = { ConsoleColor.Blue, ConsoleColor.Green, ConsoleColor.Magenta, ConsoleColor.Yellow, ConsoleColor.DarkMagenta, ConsoleColor.Cyan, ConsoleColor.DarkYellow, ConsoleColor.DarkCyan };
        private bool isMine;
        private bool isVisited;
        private bool isFlagged;
        private int content;
        private readonly int x;
        private readonly int y;

        public Cell(int x, int y, int content)
        {
            this.x = x;
            this.y = y;
            this.content = content;
        }

        public Cell(int x, int y, bool isMine)
            : this(x, y, 0)
        {
            if (isMine)
            {
                this.content = -1;
            }
            this.isMine = isMine;
        }

        #region Properties
        public int X
        {
            get
            {
                return this.x;
            }
        }

        public int Y
        {
            get
            {
                return this.y;
            }
        }

        public bool IsMine
        {
            get
            {
                return this.isMine;
            }
            set
            {
                this.isMine = value;
            }
        }

        public bool IsVisited
        {
            get
            {
                return this.isVisited;
            }
        }

        public bool IsFlagged
        {
            get
            {
                return this.isFlagged;
            }
        }

        public int Content
        {
            get
            {
                return this.content;
            }
            set
            {
                this.content = value;
            }
        }

        public static readonly string[] NotOpenedBlock =
            {
                string.Format("{0}{0}{0}", block),
                string.Format("{0}{0}{0}", block), 
                string.Format("{0}{0}{0}", block), 
                string.Format("{0}{0}{0}", block), 
                string.Format("{0}{0}{0}", block),
            };

        public static readonly string[] Flag =
            {
                "..#",
                ".##",
                "###",
                "..#",
                "###",
            };

        public static readonly string[] Mine =
            {
               "...",
               "\\|/",
               "-@-",
               "/|\\",
               "...",
            };

        public static readonly string[] ZeroBlock =
            {
                "...",
                "...",
                "...",
                "...",
                "...",
            };

        public static readonly string[] OneBlock =
            {
                ".#.",
                "##.",
                ".#.",
                ".#.",
                "###",
            };

        public static readonly string[] TwoBlock =
            {
                "###",
                "..#",
                "###",
                "#..",
                "###",
            };

        public static readonly string[] ThreeBlock =
            {
                "###",
                "..#",
                "###",
                "..#",
                "###",
            };

        public static readonly string[] FourBlock =
            {
                "#.#",
                "#.#",
                "###",
                "..#",
                "..#",
            };

        public static readonly string[] FiveBlock =
            {
                "###",
                "#..",
                "###",
                "..#",
                "###",
            };

        public static readonly string[] SixBlock =
            {
                "###",
                "#.. ",
                "### ",
                "#.# ",
                "### ",
            };

        public static readonly string[] SevenBlock =
            {
                "###",
                "..#",
                "###",
                ".#.",
                ".#.",
            };

        public static readonly string[] EightBlock =
            {
                "###",
                "#.#",
                "###",
                "#.#",
                "###",
            };
        #endregion

        public void Visit()
        {
            this.isVisited = true;
        }

        public void MakeMine()
        {
            this.isMine = true;
        }

        public void PlaceFlag()
        {
            this.isFlagged = true;
        }

        public void RemoveFlag()
        {
            this.isFlagged = false;
        }

        public void Draw(string[] block, int digit = -1, ConsoleColor color = ConsoleColor.Black, bool isMineOrFlag = false, bool recursiveCall = false)
        {
            int currentY = this.Y;
            if (recursiveCall)
            {
                color = ConsoleColor.Black;
            }

            Console.BackgroundColor = color;
            ConsoleColor digitColor = ConsoleColor.White;

            if (isMineOrFlag == true)
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }
            else if(digit !=-1)
            {
                digitColor = digitsColors[digit - 1];
            }

            Console.Write(new string(' ', 5));
            Console.SetCursorPosition(this.X, ++currentY);

            for (int blockRow = 0; blockRow < block.Length; blockRow++)
            {
                Console.BackgroundColor = color;
                Console.Write(" ");
                Console.BackgroundColor = ConsoleColor.Black;

                if (digit != -1)
                {
                    foreach (char item in block[blockRow])
                    {
                        if (item == '.')
                        {
                            Console.ForegroundColor = ConsoleColor.White;                            
                        }
                        else
                        {
                            Console.ForegroundColor = digitColor;
                        }
                        Console.Write(item);
                    }
                }
                else
                {
                    Console.Write(block[blockRow]);
                }
                
                Console.BackgroundColor = color;
                Console.Write(" ");
                Console.SetCursorPosition(x, ++currentY);
            }

            Console.BackgroundColor = color;
            Console.Write(new string(' ', 5));
            Console.ForegroundColor = ConsoleColor.Gray;
        }


        public static void DrawOnlyFrame(int x, int y, ConsoleColor color = ConsoleColor.Black)
        {
            int currentY = y;
            var oldBackGroundColor = ConsoleColor.Black;
            Console.BackgroundColor = color;
            Console.Write(new string(' ', 5));
            Console.SetCursorPosition(x, ++currentY);

            for (int blockRow = 0; blockRow < CellHeight; blockRow++)
            {
                Console.Write(" ");
                Console.SetCursorPosition(x + CellWidth + 1, currentY);
                Console.Write(" ");
                Console.SetCursorPosition(x, ++currentY);
            }

            Console.BackgroundColor = color;
            Console.Write(new string(' ', 5));
            Console.BackgroundColor = oldBackGroundColor;
        }
    }
}
